package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.StringUtil;
import com.google.errorprone.annotations.Var;
import com.zzyl.base.PageBean;
import com.zzyl.dto.ReservationDto;
import com.zzyl.dto.VisitDto;
import com.zzyl.entity.customer.Member;
import com.zzyl.entity.visit.Reservation;
import com.zzyl.entity.visit.Visit;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.ReservationStatus;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.CustomerOrderMapper;
import com.zzyl.mapper.MemberMapper;
import com.zzyl.mapper.ReservationMapper;
import com.zzyl.service.ReservationService;
import com.zzyl.service.VisitService;
import com.zzyl.utils.ThreadLocalUtil;
import com.zzyl.vo.ReservationVo;
import com.zzyl.vo.TimeCountVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class ReservationServiceImpl implements ReservationService {
	private final MemberMapper mapper;
	
	private final ReservationMapper reservationMapper;
	
	private final VisitService visitService;
	
	/**
	 * 添加预约
	 */
	@Override
	public void add(ReservationDto dto) {
		
		Long userId = ThreadLocalUtil.get();
		
		// 取消次数大于3次的也不能预约
		int cancelledReservationCount = getCancelledReservationCount(userId);
		
		// 如果已经预约的次数超过3次，则不需要再进行预约
		if (cancelledReservationCount >= 3) {
			throw new BaseException(BasicEnum.RESERVATION_CANCEL_COUNT_UPPER_LIMIT);
		}
		
		// 否则，允许添加预约
		Reservation reservation = new Reservation();
		BeanUtils.copyProperties(dto, reservation);
		reservation.setStatus(ReservationStatus.PENDING.getOrdinal());
		reservation.setCreateBy(userId);
		try {
			reservationMapper.insert(reservation);
		} catch (Exception e) {
			log.info(e + "");
			throw new BaseException(BasicEnum.TIME_ALREADY_RESERVATED_BY_PHONE);
		}
	}
	
	/**
	 * 更新预约
	 */
	@Override
	public void update(Long id, ReservationDto dto) {
		Reservation reservation = reservationMapper.findById(id);
		if (reservation != null) {
			BeanUtils.copyProperties(dto, reservation);
			reservation.setId(id);
			reservation.setUpdateTime(LocalDateTime.now());
			reservationMapper.update(reservation);
		}
	}
	
	/**
	 * 取消预约
	 */
	@Override
	public void cancelReservation(Long id) {
		Reservation reservation = reservationMapper.findById(id);
		if (reservation != null) {
			reservation.setStatus(ReservationStatus.CANCELED.getOrdinal());
			reservationMapper.update(reservation);
		}
	}
	
	/**
	 * 根据id删除预约
	 */
	@Override
	public void deleteById(Long id) {
		reservationMapper.deleteById(id);
	}
	
	/**
	 * 根据id查找预约
	 */
	@Override
	public ReservationVo findById(Long id) {
		Reservation reservation = reservationMapper.findById(id);
		if (reservation != null) {
			return convertToVO(reservation);
		}
		return null;
	}
	
	
	/**
	 * 查找所有预约
	 * @param mobile 预约人手机号
	 * @param time   预约时间
	 */
	@Override
	public List<ReservationVo> findAll(String mobile, LocalDateTime time) {
		LocalDateTime endTime = time.plusHours(24); // 计算24小时后的时间
		Long userId = ThreadLocalUtil.get();
		List<Reservation> reservations = reservationMapper.findAll(userId, mobile, time, endTime); // 根据mobile和时间范围查询预约
		return convertToVOList(reservations);
	}
	
	
	/**
	 * 分页查找预约
	 * @param page      页码
	 * @param size      每页大小
	 * @param name      预约人姓名
	 * @param phone     预约人手机号
	 * @param status    预约状态
	 * @param type      预约类型
	 * @param startTime
	 * @param endTime
	 * @return 预约列表
	 */
	@Override
	public PageBean<ReservationVo> findByPage(int page, int size, String name, String phone, Integer status, Integer type, LocalDateTime startTime, LocalDateTime endTime) {
		PageHelper.startPage(page, size);
		Long userId = ThreadLocalUtil.get();
		Page<Reservation> byPage = reservationMapper.findByPage(page, size, name, phone, status, type, userId, startTime, endTime);
		return PageBean.of(byPage, ReservationVo.class);
	}
	
	
	/**
	 * 将Reservation转换为ReservationVO
	 */
	private ReservationVo convertToVO(Reservation reservation) {
		return BeanUtil.toBean(reservation, ReservationVo.class);
	}
	
	/**
	 * 将List<Reservation>转换为List<ReservationVO>
	 */
	private List<ReservationVo> convertToVOList(List<Reservation> reservations) {
		return reservations.stream().map(this::convertToVO).collect(Collectors.toList());
	}
	
	/**
	 * 将时间戳转换为字符串
	 */
	private String convertTimeToStr(Long time) {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time));
	}
	
	/**
	 * 如果预约未完成，则将预约状态更新为过期
	 */
	@Override
	public void updateVisitReservationStatusToExpiredIfNotCompleted(Long id) {
		Reservation visitReservation = reservationMapper.findById(id);
		if (visitReservation.getStatus().equals(ReservationStatus.COMPLETED.getOrdinal())
				|| visitReservation.getStatus().equals(ReservationStatus.CANCELED.getOrdinal())) {
			return;
		}
		LocalDateTime reservationTime = visitReservation.getTime();
		LocalDateTime currentTime = LocalDateTime.now();
		if (currentTime.isAfter(reservationTime.plusHours(1))) {
			visitReservation.setStatus(ReservationStatus.EXPIRED.getOrdinal());
			reservationMapper.update(visitReservation);
		}
	}
	
	/**
	 * 查询每个时间段剩余预约次数
	 * @param time 时间 日
	 * @return 每个时间段剩余预约次数
	 */
	@Override
	public List<TimeCountVo> countReservationsForEachTimeWithinTimeRange(LocalDateTime time) {
		LocalDateTime endTime = time.plusHours(24);
		return reservationMapper.countReservationsByTimeRange(time, endTime);
	}
	
	/**
	 * 获取取消预约次数
	 * @param updateBy 更新人id
	 * @return 取消预约次数
	 */
	@Override
	public int getCancelledReservationCount(Long updateBy) {
		return reservationMapper.countCancelledReservationsWithinTimeRange(LocalDateTime.now().withHour(0).withMinute(0).withSecond(0),
				LocalDateTime.now().withHour(23).withMinute(59).withSecond(59), updateBy);
	}
	
	/**
	 * 来访
	 * @param id   ID
	 * @param time 时间
	 */
	@Override
	public void visit(Long id, Long time) {
		Reservation reservation = reservationMapper.findById(id);
		if (reservation != null) {
			reservation.setStatus(ReservationStatus.COMPLETED.getOrdinal());
			reservationMapper.update(reservation);
			VisitDto visitDto = BeanUtil.toBean(reservation, VisitDto.class);
			visitDto.setTime(LocalDateTimeUtil.of(time));
			visitService.add(visitDto);
		}
	}
	
	@Override
	public void updateReservationStatus(LocalDateTime now) {
		reservationMapper.updateReservationStatus(now);
	}

	/**
	 * 取消预约
	 * userId用户id
	 */
	@Override
	public Object cancelledCount() {
		//在线程里面拿到当前用户id
		Long userId = ThreadLocalUtil.get();
		System.out.println("111111---------------------------"+userId);
		/*
		* name,根据id拿到名字走预约表
		* */
		Member member = mapper.cancelledCount(userId);
		Integer status =  reservationMapper.cancelledCount(member.getName());
		System.out.println("----------------------"+status);
		if (status!=null){
			if (status>=3){
				throw new BaseException(BasicEnum.CANCEL_RESERVATION_OVER_LIMIT_ERROR);
			}
			return status;
		}else {
			ReservationVo reservationVo = BeanUtil.toBean(member, ReservationVo.class);
			reservationVo.setStatus(0);	
			reservationVo.setType(0);
			reservationVo.setTime(LocalDateTime.now());
			reservationVo.setVisitor("");
			reservationVo.setMobile(member.getPhone());
			reservationMapper.foundName(reservationVo);
			return 0;
		}
	}

	/**
	 * @param time 
	 * @return
	 */
	@Override
	public List<TimeCountVo> countByTime(Long time) {
		
		
		
		//用LocalDateTimeUtil工具包直接转换值
		LocalDateTime localDateTime = LocalDateTimeUtil.of(time);
		//2024-11-11 00:00:00.00
		
		System.out.println(localDateTime);
//		Integer year = localDateTime.getYear();
		LocalDate date = localDateTime.toLocalDate();
		//2024:11-11
		//DateTimeFormatter转化器设置格式
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
		//转换
		//2024-11-11
		String format = date.format(dateTimeFormatter);
		List<TimeCountVo> list =  reservationMapper.countByTime(format);
		return list;
	}

	/**
	 * @param  
	 */
	@Override
	public void postCount(Visit visit) {
		//正则表达式
		String regex = "^\\d{10,11}$";
		System.out.println("visitDto------------"+visit);
		//预约内容不能为空
		if (BeanUtil.isEmpty(visit)){
			throw new BaseException(BasicEnum.POST_COUNT_ERROR);
		}
		//手机号格式错误	
		if (!visit.getMobile().matches(regex)){
			throw new BaseException(BasicEnum.MOBILE_ERROR);
		}
		//预约时间不能重复
		if (reservationMapper.postCountPhone(visit.getMobile())==visit.getTime()){
			throw new BaseException(BasicEnum.Phone_Time_Error);
		}
		//预约人不存在
		if (BeanUtil.isNotEmpty(reservationMapper.inoutRetreat(visit.getVisitor()))){
			throw new BaseException(BasicEnum.Name_Error);
		}
		visit.setStatus(0);
		visit.setCreateBy(ThreadLocalUtil.get());
		reservationMapper.postCount(visit);
	}

	/**
	 * @return 
	 */
	@Override
	public PageBean<ReservationVo> pageCount(Integer pageNum, Integer pageSize, Integer status) {
		System.out.println(pageNum);
		System.out.println(pageSize);
		Long userId = ThreadLocalUtil.get();
		PageHelper.startPage(pageNum,pageSize);
		Page<ReservationVo> list = reservationMapper.pageCount(status,userId);
		return PageBean.of(list);
	}

	/**取消预约的id
	 * @param id 
	 */
	@Override
	public void clearCount(Long id) {
		reservationMapper.clearCount(id);
	}
}

